﻿using System;
using NUnit.Framework;
using ANX.Framework.Content.Pipeline.Helpers.HLSLParser;

// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license

namespace ANX.Framework.TestCenter.HLSLParser
{
    public static class VariableTests
    {
        #region TestGetTypeModifiersFromEmptyString
        [Test]
        public static void TestGetTypeModifiersFromEmptyString()
        {
            Assert.AreEqual(Variable.GetTypeModifiers(null), new string[0]);
            Assert.AreEqual(Variable.GetTypeModifiers(new ParseTextWalker("")),
                new string[0]);
        }
        #endregion

        #region TestGetTypeModifiersStringWithoutElement
        [Test]
        public static void TestGetTypeModifiersStringWithoutElement()
        {
            var text = new ParseTextWalker("aaa");
            string[] result = Variable.GetTypeModifiers(text);
            Assert.AreEqual(0, result.Length);
        }
        #endregion

        #region TestGetTypeModifiersFromStringWithoutSpace
        [Test]
        public static void TestGetTypeModifiersFromStringWithoutSpace()
        {
            var text = new ParseTextWalker("uniform");
            string[] result = Variable.GetTypeModifiers(text);
            Assert.AreEqual(1, result.Length);
            Assert.AreEqual("uniform", result[0]);
        }
        #endregion

        #region TestGetStorageClassesFrom
        [Test]
        public static void TestGetStorageClassesFrom()
        {
            var text = new ParseTextWalker("uniform extern float4x4 MatrixTransform;");
            string[] result = Variable.GetTypeModifiers(text);
            Assert.AreEqual(2, result.Length);
            Assert.AreEqual("uniform", result[0]);
            Assert.AreEqual("extern", result[1]);
        }
        #endregion

        #region TestIsVariableFollowing
        [Test]
        public static void TestIsVariableFollowing()
        {
            var text = new ParseTextWalker("int value;");
            bool result = Variable.IsVariableFollowing(text);
            Assert.True(result);

            text = new ParseTextWalker("int4x4 value;");
            result = Variable.IsVariableFollowing(text);
            Assert.True(result);

            text = new ParseTextWalker("const int value;");
            result = Variable.IsVariableFollowing(text);
            Assert.False(result);
        }
        #endregion

        #region TestParseIfVariable
        [Test]
        public static void TestParseIfVariable()
        {
            var text = new ParseTextWalker("int value;");
            var result = Variable.TryParse(text);
            Assert.NotNull(result);

            text = new ParseTextWalker("uniform const int value;");
            result = Variable.TryParse(text);
            Assert.NotNull(result);

            text = new ParseTextWalker("uniform extern float4x4 MatrixTransform;");
            result = Variable.TryParse(text);
            Assert.NotNull(result);

            text = new ParseTextWalker("PS_IN VS(VS_IN in) { }");
            result = Variable.TryParse(text);
            Assert.Null(result);
        }
        #endregion

        #region TestParseTwoVariables
        [Test]
        public static void TestParseTwoVariables()
        {
            string source =
                @"uniform extern float4x4 MatrixTransform;

Texture2D<float4> Texture : register(t0);";

            var text = new ParseTextWalker(source);
            var result = Variable.TryParse(text);

            Assert.NotNull(result);
            Assert.AreEqual("uniform extern float4x4 MatrixTransform;", result.ToString());
        }
        #endregion

        #region TestParseIfVariableWithGenericTexture2D
        [Test]
        public static void TestParseIfVariableWithGenericTexture2D()
        {
            string variableSource = "Texture2D <float4> Texture : register(t0);";
            var text = new ParseTextWalker(variableSource);
            var result = Variable.TryParse(text);
            Assert.NotNull(result);
            Assert.AreEqual("Texture2D<float4>", result.Type);
            Assert.AreEqual("Texture", result.Name);
            Assert.AreEqual("register(t0)", result.Register);
            Assert.AreEqual("Texture2D<float4> Texture : register(t0);", result.ToString());
        }
        #endregion

        #region TestfloatVariableParsing
        [Test]
        public static void TestfloatVariableParsing()
        {
            var text = new ParseTextWalker("uniform const float value;");
            var result = Variable.TryParse(text);
            Assert.NotNull(result);
            Assert.AreEqual(2, result.TypeModifiers.Length);
            Assert.AreEqual("float", result.Type);
        }
        #endregion

        #region TestVectorVariableParsing
        [Test]
        public static void TestVectorVariableParsing()
        {
            var text = new ParseTextWalker("vector<float, 1> value;");
            var result = Variable.TryParse(text);
            Assert.NotNull(result);
            Assert.AreEqual("float", result.Type);
            Assert.AreEqual(1, result.Dimensions.Length);
            Assert.AreEqual(1, result.Dimensions[0]);

            text = new ParseTextWalker("float4 value;");
            result = Variable.TryParse(text);
            Assert.NotNull(result);
            Assert.AreEqual("float", result.Type);
            Assert.AreEqual(1, result.Dimensions.Length);
            Assert.AreEqual(4, result.Dimensions[0]);
        }
        #endregion

        #region TestMatrixVariableParsing
        [Test]
        public static void TestMatrixVariableParsing()
        {
            var text = new ParseTextWalker("matrix<float, 1, 3> value;");
            var result = Variable.TryParse(text);
            Assert.NotNull(result);
            Assert.AreEqual("float", result.Type);
            Assert.AreEqual(2, result.Dimensions.Length);
            Assert.AreEqual(1, result.Dimensions[0]);
            Assert.AreEqual(3, result.Dimensions[1]);

            text = new ParseTextWalker("int4x4 value;");
            result = Variable.TryParse(text);
            Assert.NotNull(result);
            Assert.AreEqual("int", result.Type);
            Assert.AreEqual(2, result.Dimensions.Length);
            Assert.AreEqual(4, result.Dimensions[0]);
            Assert.AreEqual(4, result.Dimensions[1]);
        }
        #endregion

        #region TestNameParsing
        [Test]
        public static void TestNameParsing()
        {
            var text = new ParseTextWalker("matrix<float, 1, 3> value;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
        }
        #endregion

        #region TestArrayParsing
        [Test]
        public static void TestArrayParsing()
        {
            var text = new ParseTextWalker("int value[15];");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual(15, result.ArraySize);
        }
        #endregion

        #region TestInitialValueParsing
        [Test]
        public static void TestInitialValueParsing()
        {
            var text = new ParseTextWalker("int value = 4;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("4", result.InitialValue);
        }
        #endregion

        #region TestInitialValueParsingWithoutValueText
        [Test]
        public static void TestInitialValueParsingWithoutValueText()
        {
            var text = new ParseTextWalker("int value;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual(null, result.InitialValue);
        }
        #endregion

        #region TestAnnotationsParsing
        [Test]
        public static void TestAnnotationsParsing()
        {
            var text = new ParseTextWalker("int value<float y=1.3;>;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("float y=1.3;", result.Annotations);
        }
        #endregion

        #region TestAnnotationsParsingWithInitialValue
        [Test]
        public static void TestAnnotationsParsingWithInitialValue()
        {
            var text = new ParseTextWalker("int value<float y=1.3;> = 4;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("float y=1.3;", result.Annotations);
            Assert.AreEqual("4", result.InitialValue);
        }
        #endregion

        #region TestSemanticParsing
        [Test]
        public static void TestSemanticParsing()
        {
            var text = new ParseTextWalker("int value : COLOR;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("COLOR", result.Semantic);
        }
        #endregion

        #region TestSemanticParsingWithAnnotations
        [Test]
        public static void TestSemanticParsingWithAnnotations()
        {
            var text = new ParseTextWalker("int value : COLOR<float y=1.3;>;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("COLOR", result.Semantic);
            Assert.AreEqual("float y=1.3;", result.Annotations);
        }
        #endregion

        #region TestSemanticParsingWithInitialValue
        [Test]
        public static void TestSemanticParsingWithInitialValue()
        {
            var text = new ParseTextWalker("int value : COLOR = 5;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("COLOR", result.Semantic);
            Assert.AreEqual("5", result.InitialValue);
        }
        #endregion

        #region TestSemanticParsingWithoutSpaces
        [Test]
        public static void TestSemanticParsingWithoutSpaces()
        {
            var text = new ParseTextWalker("int value:COLOR;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("COLOR", result.Semantic);
        }
        #endregion

        #region TestPackoffsetParsing
        [Test]
        public static void TestPackoffsetParsing()
        {
            var text = new ParseTextWalker("int value : packoffset(c0);");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("packoffset(c0)", result.Packoffset);
        }
        #endregion

        #region TestRegisterParsing
        [Test]
        public static void TestRegisterParsing()
        {
            var text = new ParseTextWalker("int value : register( ps_5_0, s );");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("register( ps_5_0, s )", result.Register);
        }
        #endregion

        #region TestRegisterAndAnnotationParsing
        [Test]
        public static void TestRegisterAndAnnotationParsing()
        {
            var text = new ParseTextWalker(
                "int value : register( ps_5_0, s ) <float y=1.3;>;");
            var result = Variable.TryParse(text);

            Assert.AreEqual("value", result.Name);
            Assert.AreEqual("register( ps_5_0, s )", result.Register);
            Assert.AreEqual("float y=1.3;", result.Annotations);
        }
        #endregion

        #region TestToString
        [Test]
        public static void TestToString()
        {
            string variableText = "uniform const int value : COLOR <float y=1.3;> = 5;";
            var walker = new ParseTextWalker(variableText);
            var result = Variable.TryParse(walker);

            Assert.AreEqual(variableText, result.ToString());
        }
        #endregion

        #region TestToStringWithArraySize
        [Test]
        public static void TestToStringWithArraySize()
        {
            string variableText = "uniform const int value[7];";
            var walker = new ParseTextWalker(variableText);
            var result = Variable.TryParse(walker);

            Assert.AreEqual(variableText, result.ToString());
        }
        #endregion

        #region TestToStringWithPackoffset
        [Test]
        public static void TestToStringWithPackoffset()
        {
            string variableText = "uniform const int value : packoffset(c0) = 5;";
            var walker = new ParseTextWalker(variableText);
            var result = Variable.TryParse(walker);

            Assert.AreEqual(variableText, result.ToString());
        }
        #endregion

        #region TestToStringWithRegister
        [Test]
        public static void TestToStringWithRegister()
        {
            string variableText = "uniform const int value : register( vs, s[8] ) = 5;";
            var walker = new ParseTextWalker(variableText);
            var result = Variable.TryParse(walker);

            Assert.AreEqual(variableText, result.ToString());
        }
        #endregion

        #region TestToStringWithDimensions
        [Test]
        public static void TestToStringWithDimensions()
        {
            string variableText = "float4x4 matrix;";
            var walker = new ParseTextWalker(variableText);
            var result = Variable.TryParse(walker);

            Assert.AreEqual(variableText, result.ToString());
        }
        #endregion
    }
}

